package net.zigin.nhi.waste.view.depotin;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattService;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.gyf.immersionbar.ImmersionBar;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerResult;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.ui.RecognizerDialog;
import com.iflytek.cloud.ui.RecognizerDialogListener;
import com.tbruyelle.rxpermissions2.RxPermissions;

import net.zigin.nhi.waste.R;
import net.zigin.nhi.waste.adapter.BatchCheckAdapter;
import net.zigin.nhi.waste.bean.BatchCheckBean;
import net.zigin.nhi.waste.bean.BatchInBean;
import net.zigin.nhi.waste.constants.Constants;
import net.zigin.nhi.waste.net.ApiCall;
import net.zigin.nhi.waste.net.BaseResponse;
import net.zigin.nhi.waste.net.HttpRetrofitClient;
import net.zigin.nhi.waste.net.PublicService;
import net.zigin.nhi.waste.utils.GravityUnitUtils;
import net.zigin.nhi.waste.utils.JsonParser;
import net.zigin.nhi.waste.utils.StringUtil;
import net.zigin.nhi.waste.view.ble.BleSearchActivity;
import net.zigin.nhi.waste.view.depotout.OutPrintActivity;
import net.zigin.nhi.waste.view.widget.AlarmOutDialog;
import net.zigin.nhi.waste.view.widget.DialogManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import io.paperdb.Paper;
import io.reactivex.Observable;

/**
 * 批量入库核对重量界面
 */
public class BatchInCheckActivity extends AppCompatActivity implements View.OnClickListener {

    private LinearLayout mConnectState;
    private ImageView mImgConnect;
    private TextView mTvConnect;
    private TextView mBoxNum;
    private TextView mCollectWeight;
    private EditText mCurrentWeight;
    private Button mReRead;
    private TextView mDifference;
    private RecyclerView mRvBatch;
    private Button mBtnSpeech;
    private EditText mRemark;
    private Button mBtnComplete;

    private String uuid_service;
    private String uuid_character;
    private String gravity;

    // 语音听写对象
    private SpeechRecognizer mIat;
    // 语音听写UI
    private RecognizerDialog mIatDialog;

    private BatchCheckAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_batch_in_check);

        initView();
        // 初始化识别无UI识别对象
        // 使用SpeechRecognizer对象，可根据回调消息自定义界面；
        mIat = SpeechRecognizer.createRecognizer(this, mInitListener);
        // 初始化听写Dialog，如果只使用有UI听写功能，无需创建SpeechRecognizer
        // 使用UI听写功能，请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
        mIatDialog = new RecognizerDialog(this, mInitListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        uuid_service = Paper.book().read(Constants.UUID_SERVICE);
        uuid_character = Paper.book().read(Constants.UUID_CHARACTER);
        BleManager.getInstance().enableBluetooth();
        connectBle();

        getWasteDetail();

        mCurrentWeight.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if (mCurrentWeight.getText().toString().contains(".")) {
                    if (mCurrentWeight.getText().toString().indexOf(".", mCurrentWeight.getText().toString().indexOf(".") + 1) > 0) {
                        Toast.makeText(getApplicationContext(), "已经输入\".\"不能重复输入", Toast.LENGTH_SHORT).show();
                        mCurrentWeight.setText(mCurrentWeight.getText().toString().substring(0, mCurrentWeight.getText().toString().length() - 1));
                        mCurrentWeight.setSelection(mCurrentWeight.getText().toString().length());
                    }
                }
            }

            @SuppressLint("DefaultLocale")
            @Override
            public void afterTextChanged(Editable s) {
                if (StringUtil.isNotEmpty(mCollectWeight.getText().toString()) && StringUtil.isNotEmpty(mCurrentWeight.getText().toString())) {
                    double collWeight = Double.parseDouble(mCollectWeight.getText().toString());
                    if (!mCurrentWeight.getText().toString().equals(".")) {
                        double currWeight = Double.parseDouble(mCurrentWeight.getText().toString());
                        double res = Math.abs(collWeight - currWeight);
                        mDifference.setText(String.format("%.2f", res));
                    }
                }
            }
        });
    }

    private void initView() {
        ImmersionBar.with(this).init();
        mConnectState = findViewById(R.id.connect_state);
        mImgConnect = findViewById(R.id.img_connect);
        mTvConnect = findViewById(R.id.tv_connect);
        mBoxNum = findViewById(R.id.box_num);
        mCollectWeight = findViewById(R.id.collect_weight);
        mCurrentWeight = findViewById(R.id.current_weight);
        mReRead = findViewById(R.id.reRead);
        mDifference = findViewById(R.id.difference);
        mRvBatch = findViewById(R.id.rv_batch);
        mBtnSpeech = findViewById(R.id.btnSpeech);
        mRemark = findViewById(R.id.remark);
        mBtnComplete = findViewById(R.id.btnComplete);

        mConnectState.setOnClickListener(this);
        mReRead.setOnClickListener(this);
        mBtnSpeech.setOnClickListener(this);
        mBtnComplete.setOnClickListener(this);

        mRvBatch.setLayoutManager(new LinearLayoutManager(this));
    }

    /**
     * 初始化监听器。
     */
    private InitListener mInitListener = code -> {
        Log.d("语音听写", "SpeechRecognizer init() code = " + code);
        if (code != ErrorCode.SUCCESS) {
            Toast.makeText(BatchInCheckActivity.this, "语音听写初始化失败", Toast.LENGTH_SHORT).show();
        }
    };

    /**
     * 听写UI监听器
     */
    private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
        public void onResult(RecognizerResult results, boolean isLast) {
            Log.d("语音听写", "recognizer result：" + results.getResultString());

            String text = JsonParser.parseIatResult(results.getResultString());
            mRemark.append(text);
            mRemark.setSelection(mRemark.length());
        }

        /**
         * 识别回调错误.
         */
        public void onError(SpeechError error) {
            Toast.makeText(BatchInCheckActivity.this, error.getPlainDescription(true), Toast.LENGTH_SHORT).show();
        }
    };

    /**
     * 参数设置
     */
    public void setParam() {
        // 清空参数
//        mIat.setParameter(SpeechConstant.PARAMS, null);
        String lag = "en_us";
        // 设置引擎
        mIat.setParameter(SpeechConstant.ENGINE_TYPE, "cloud");
        // 设置返回结果格式
        mIat.setParameter(SpeechConstant.RESULT_TYPE, "json");
        // 设置语言
        mIat.setParameter(SpeechConstant.LANGUAGE, "en_us");
        mIat.setParameter(SpeechConstant.ACCENT, null);
        // 设置语言
        mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
        // 设置语言区域
        mIat.setParameter(SpeechConstant.ACCENT, lag);
        // 设置语音前端点:静音超时时间，即用户多长时间不说话则当做超时处理
        mIat.setParameter(SpeechConstant.VAD_BOS, "4000");

        // 设置语音后端点:后端点静音检测时间，即用户停止说话多长时间内即认为不再输入， 自动停止录音
        mIat.setParameter(SpeechConstant.VAD_EOS, "1000");

        // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
        mIat.setParameter(SpeechConstant.ASR_PTT, "1");

        // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
        mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,
                getExternalFilesDir("msc").getAbsolutePath() + "/iat.wav");
    }

    /**
     * 每次进此界面, 如果此时没有连接中的蓝牙，自动去连接数据库中记录的连接过的蓝牙设备
     */
    private void connectBle() {
        if (!Constants.BLE_CONNECT_STATE) {
            mConnectState.setBackgroundColor(Color.parseColor("#F0E2E0"));
            mImgConnect.setImageResource(R.drawable.img_connect_fail);
            mTvConnect.setText("蓝牙称连接失败，请重新连接");
            mTvConnect.setTextColor(Color.parseColor("#F4664A"));

            Set<String> macSet = Paper.book().read(Constants.BLEMACS);
            //判断数据库中是否存在已记录的MAC。有就直接连接，没有则显示未连接状态栏
            if (macSet != null && macSet.size() > 0) {
                for (String mac : macSet) {
                    BleManager.getInstance().connect(mac, new BleGattCallback() {
                        @Override
                        public void onStartConnect() {

                        }

                        @Override
                        public void onConnectFail(BleDevice bleDevice, BleException exception) {
                            Log.i("连接情况", "连接失败！");
                        }

                        @Override
                        public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                            Log.i("连接情况", "连接成功！");
                            Constants.BLEDEVICE = bleDevice;

                            List<BluetoothGattService> serviceList = gatt.getServices();
                            if (bleDevice.getName().contains("Furi")) {
                                uuid_service = serviceList.get(3).getUuid().toString();
                                uuid_character = serviceList.get(3).getCharacteristics().get(0).getUuid().toString();
                            }

                            if (bleDevice.getName().equals("HC-42")) {
                                if (serviceList.size() > 2) {
                                    uuid_service = serviceList.get(2).getUuid().toString();
                                    if (serviceList.get(2).getCharacteristics().size() > 0) {
                                        uuid_character = serviceList.get(2).getCharacteristics().get(0).getUuid().toString();
                                    }
                                }
                            }

                            runOnUiThread(() -> {
                                mConnectState.setBackgroundColor(Color.parseColor("#F2EAD7"));
                                mImgConnect.setImageResource(R.drawable.img_connect_success);
                                mTvConnect.setText("蓝牙称连接成功");
                                mTvConnect.setTextColor(Color.parseColor("#FFAA00"));
                            });

                        }

                        @Override
                        public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                            if (isActiveDisConnected) {
                                Log.i("连接情况", "断开连接");
                            }
                        }
                    });
                }
            }
        } else {
            mConnectState.setBackgroundColor(Color.parseColor("#F2EAD7"));
            mImgConnect.setImageResource(R.drawable.img_connect_success);
            mTvConnect.setText("蓝牙称连接成功");
            mTvConnect.setTextColor(Color.parseColor("#FFAA00"));
        }
    }

    /**
     * 获取医废详情
     */
    private void getWasteDetail() {
        Map<String, Object> map = new HashMap<>();
        map.put("ids", Paper.book().read(Constants.IN_CHECK));
        Observable<BaseResponse<String>> observable = HttpRetrofitClient.getInstance().create(PublicService.class)
                .getListWithWeightByIds(Paper.book().read(Constants.TOKEN), map);
        HttpRetrofitClient.execute(observable, new ApiCall<String>() {
            @SuppressLint("DefaultLocale")
            @Override
            protected void success(String data) {
                Log.i("批量出入库详情", data);
                JSONObject object = JSON.parseObject(data);
                double weight = Double.parseDouble(object.getString("weight"));
                mCollectWeight.setText(String.format("%.2f", weight));
                mCurrentWeight.setHint(String.format("%.2f", weight));
                List<BatchCheckBean> list = JSONArray.parseArray(object.getString("wasteBases"), BatchCheckBean.class);
                adapter = new BatchCheckAdapter(list);
                mRvBatch.setAdapter(adapter);
            }
        });

    }

    @SuppressLint({"NonConstantResourceId", "DefaultLocale"})
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.connect_state:  //顶部蓝牙连接状态栏
                Intent intent1 = new Intent(BatchInCheckActivity.this, BleSearchActivity.class);
                startActivity(intent1);
                break;
            case R.id.reRead: //重新读取按钮
                if (Constants.BLEDEVICE != null) {
                    receiveBleData();
                }
                new Handler().postDelayed(() -> {
                    BleManager.getInstance().stopNotify(Constants.BLEDEVICE, uuid_service, uuid_character);
                    GravityUnitUtils utils = new GravityUnitUtils();
                    mCurrentWeight.setText(utils.getGravity(BatchInCheckActivity.this, gravity));
                    if (StringUtil.isNotEmpty(mCollectWeight.getText().toString()) && StringUtil.isNotEmpty(mCurrentWeight.getText().toString())) {
                        double collWeight = Double.parseDouble(mCollectWeight.getText().toString());
                        double currWeight = Double.parseDouble(mCurrentWeight.getText().toString());
                        double res = Math.abs(collWeight - currWeight);
                        mDifference.setText(String.format("%.2f", res));
                    }
                }, 700);
                break;
            case R.id.btnSpeech:  //语音按钮
                RxPermissions permissions = new RxPermissions(this);
                permissions.request(Manifest.permission.RECORD_AUDIO)
                        .subscribe(granted -> {
                            if (!granted) { //申请失败
                                Toast.makeText(this, "权限未开启, 将无法识别语音！", Toast.LENGTH_SHORT).show();
                            } else {
                                speechToText();
                            }
                        });
                break;
            case R.id.btnComplete: //完成入库按钮

                String currentWeight = mCurrentWeight.getText().toString().trim();
                if (TextUtils.isEmpty(currentWeight)) {
                    currentWeight = mCurrentWeight.getHint().toString().trim();
                }
                Map<String, Object> map = new HashMap<>();
                map.put("wasteBaseIds", Paper.book().read(Constants.IN_CHECK));
                map.put("collectUserId", Paper.book().read(Constants.COLLECTOR_ID));
                map.put("weight", currentWeight);
                if (StringUtil.isNotEmpty(mRemark.getText().toString())) {
                    map.put("remark", mRemark.getText().toString());
                }
                Observable<BaseResponse<String>> observable = HttpRetrofitClient.getInstance().create(PublicService.class)
                        .putMultipleInStorage(Paper.book().read(Constants.TOKEN), map);
                DialogManager.getInstance().showLoading(this);
                HttpRetrofitClient.execute(observable, new ApiCall<String>() {
                    @Override
                    protected void success(String data) {
                        Toast.makeText(v.getContext(), "批量入库成功！", Toast.LENGTH_SHORT).show();
                        finish();
                    }
                });
                break;

            default:
                break;
        }
    }

    /**
     * 开启通知并监听接收蓝牙数据
     */
    private void receiveBleData() {
        if (StringUtil.isNotEmpty(uuid_service) && StringUtil.isNotEmpty(uuid_character)) {
            BleManager.getInstance().notify(Constants.BLEDEVICE, uuid_service, uuid_character, new BleNotifyCallback() {
                @Override
                public void onNotifySuccess() {
                    Log.i("打开通知", "操作成功！");
                }

                @Override
                public void onNotifyFailure(BleException exception) {
                    Log.i("打开通知", "操作失败！");
                }

                @Override
                public void onCharacteristicChanged(byte[] data) {
                    //打开通知后，设备发过来的数据将在这里出现
                    if (data != null && data.length > 0) {
                        StringBuilder stringBuilder = new StringBuilder(data.length);

                        for (byte byteChar : data) {
                            stringBuilder.append(String.format("%02X ", byteChar));
                        }
                        Log.i("重量", new String(data) + "\n");
                        gravity = new String(data);
                    }
                }
            });
        }
    }

    /**
     * 开启语音识别对话框，将说的话转成文字
     */
    private void speechToText() {
        setParam();
        // 显示听写对话框
        mIatDialog.setListener(mRecognizerDialogListener);
        mIatDialog.show();
        TextView txt = mIatDialog.getWindow().getDecorView().findViewWithTag("textlink");
        txt.setText("");
        txt.getPaint().setFlags(Paint.SUBPIXEL_TEXT_FLAG);//取消下划线
        txt.setEnabled(false);
        Toast.makeText(BatchInCheckActivity.this, "请开始说话...", Toast.LENGTH_SHORT).show();
    }
}